﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TagRepositoryTest.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the TagRepositoryTest type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Data.Tests
{
    using System.Collections.Generic;
    using System.Data.Objects;
    using System.Linq;
    using Entities;
    using Interfaces;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;

    /// <summary>
    /// Defines the <seealso cref="Hisaab.Data.Tests.TagRepositoryTest"/> type.
    /// </summary>
    [TestClass]
    public class TagRepositoryTest
    {
        #region Tag Tests

        #region Query Tests

        /// <summary>
        /// Tags the data manager get Tags test with empty repository.
        /// </summary>
        [TestMethod]
        public void TagDataManagerQueryShouldReturnEmptyListWithEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.Query(new Tag(), null, null);
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Count());
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Tags the data manager get Tags test with non empty repository.
        /// </summary>
        [TestMethod]
        public void TagDataManagerQueryShouldReturnNonEmptyListWithNonEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            mockObjectSet.AddObject(new Tag { Id = 2, Name = "Tag 2" });
            mockObjectSet.AddObject(new Tag { Id = 3, Name = "Tag 3" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.Query(new Tag(), null, null);
            Assert.IsNotNull(result);
            Assert.AreEqual(3, result.Count());
            Assert.AreEqual(1, result.ElementAt(0).Id);
            Assert.AreEqual("Tag 1", result.ElementAt(0).Name);
            Assert.AreEqual(2, result.ElementAt(1).Id);
            Assert.AreEqual("Tag 2", result.ElementAt(1).Name);
            Assert.AreEqual(3, result.ElementAt(2).Id);
            Assert.AreEqual("Tag 3", result.ElementAt(2).Name);
            mockRepository.VerifyAll();
        }

        #endregion Query Tests

        #region Filter Tests

        /// <summary>
        /// Tags the data manager get Tags test with empty repository.
        /// </summary>
        [TestMethod]
        public void TagDataManagerFilterShouldReturnEmptyListWithEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.Filter(x => true, null, null);
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Count());
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Tags the data manager get Tags test with non empty repository.
        /// </summary>
        [TestMethod]
        public void TagDataManagerFilterShouldReturnNonEmptyListWithNonEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            mockObjectSet.AddObject(new Tag { Id = 2, Name = "Tag 2" });
            mockObjectSet.AddObject(new Tag { Id = 3, Name = "Tag 3" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.Filter(x => true, null, null);
            Assert.IsNotNull(result);
            Assert.AreEqual(3, result.Count());
            Assert.AreEqual(1, result.ElementAt(0).Id);
            Assert.AreEqual("Tag 1", result.ElementAt(0).Name);
            Assert.AreEqual(2, result.ElementAt(1).Id);
            Assert.AreEqual("Tag 2", result.ElementAt(1).Name);
            Assert.AreEqual(3, result.ElementAt(2).Id);
            Assert.AreEqual("Tag 3", result.ElementAt(2).Name);
            mockRepository.VerifyAll();
        }

        #endregion Filter Tests

        #region GetById Tests

        /// <summary>
        /// Get by id test with empty repository
        /// </summary>
        [TestMethod]
        public void TagDataManagerFindByIdShouldReturnNullWithEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.FindById(1);
            Assert.IsNull(result);
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Get by id test with repository with records
        /// </summary>
        [TestMethod]
        public void TagDataManagerFindByIdShouldReturnMatchingTag()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            mockObjectSet.AddObject(new Tag { Id = 2, Name = "Tag 2" });
            mockObjectSet.AddObject(new Tag { Id = 3, Name = "Tag 3" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.FindById(2);
            Assert.IsNotNull(result);
            Assert.AreEqual(2, result.Id);
            Assert.AreEqual("Tag 2", result.Name);
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Tags the data manager find by id should return null with no matching tag.
        /// </summary>
        [TestMethod]
        public void TagDataManagerFindByIdShouldReturnNullWithNoMatchingTag()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            mockObjectSet.AddObject(new Tag { Id = 2, Name = "Tag 2" });
            mockObjectSet.AddObject(new Tag { Id = 3, Name = "Tag 3" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.FindById(20);
            Assert.IsNull(result);
            mockRepository.VerifyAll();
        }

        #endregion GetById Tests

        #region GetTagsForTransaction Tests

        /// <summary>
        /// Tags the data manager get tags for transaction should return null with empty repository.
        /// </summary>
        [TestMethod]
        public void TagDataManagerGetTagsForTransactionShouldReturnEmptyListWithEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.GetTagsForTransaction(1);
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Count());
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Tags the data manager get tags for transaction should return matching tag.
        /// </summary>
        [TestMethod]
        public void TagDataManagerGetTagsForTransactionShouldReturnMatchingTag()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1", Transactions = new List<Transaction> { new Transaction { Id = 1 } } });
            mockObjectSet.AddObject(new Tag { Id = 2, Name = "Tag 2", Transactions = new List<Transaction> { new Transaction { Id = 2 } } });
            mockObjectSet.AddObject(new Tag { Id = 3, Name = "Tag 3", Transactions = new List<Transaction> { new Transaction { Id = 3 } } });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.GetTagsForTransaction(2);
            Assert.IsNotNull(result);
            Assert.AreNotEqual(0, result.Count());
            Assert.AreEqual(2, result.ElementAt(0).Id);
            Assert.AreEqual("Tag 2", result.ElementAt(0).Name);
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Tags the data manager get tags for transaction should return null with no matching tag.
        /// </summary>
        [TestMethod]
        public void TagDataManagerGetTagsForTransactionShouldReturnEmptyListWithNoMatchingTransaction()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1", Transactions = new List<Transaction> { new Transaction { Id = 1 } } });
            mockObjectSet.AddObject(new Tag { Id = 2, Name = "Tag 2", Transactions = new List<Transaction> { new Transaction { Id = 2 } } });
            mockObjectSet.AddObject(new Tag { Id = 3, Name = "Tag 3", Transactions = new List<Transaction> { new Transaction { Id = 3 } } });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.GetTagsForTransaction(20);
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Count());
            mockRepository.VerifyAll();
        }

        #endregion GetTagsForTransaction Tests

        #region Insert Tests

        /// <summary>
        /// Email template dao insert test with empty repository
        /// </summary>
        [TestMethod]
        public void TagDataManagerInsertTagTestWithEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            mockRepository.Setup(m => m.SaveChanges());
            mockRepository.Setup(m => m.Refresh(RefreshMode.StoreWins, It.IsAny<Tag>()));
            var dao = new TagRepository(mockRepository.Object);
            var result = dao.Add(new Tag { Id = 1, Name = "Tag 1" });
            Assert.AreEqual(1, mockObjectSet.Count());
            Assert.IsNotNull(result);
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Email template dao insert test with existing records in repository
        /// </summary>
        [TestMethod]
        public void TagDataManagerInsertTagTestWithNonEmptyRepository()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            mockRepository.Setup(m => m.SaveChanges());
            mockRepository.Setup(m => m.Refresh(RefreshMode.StoreWins, It.IsAny<Tag>()));
            var dao = new TagRepository(mockRepository.Object);

            Assert.AreEqual(1, mockObjectSet.Count());

            var result = dao.Add(new Tag { Id = 2, Name = "Tag 2" });

            Assert.AreEqual(2, mockObjectSet.Count());
            Assert.IsNotNull(result);
            mockRepository.VerifyAll();
        }

        #endregion Insert Tests

        #region Udpate Tests

        /// <summary>
        /// Email template dao update test with no matching record
        /// </summary>
        [TestMethod]
        public void TagDataManagerUpdateTagTestWithNoMatchingRecord()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            dao.Update(new Tag { Id = 2, Name = "Tag 2" });

            Assert.AreEqual(1, mockObjectSet.Count());
            mockRepository.VerifyAll();
        }

        /// <summary>
        /// Email template dao update test with matching record
        /// </summary>
        [TestMethod]
        public void TagDataManagerUpdateTagTestWithMatchingRecord()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            mockRepository.Setup(m => m.SaveChanges()).Returns(1);

            var dao = new TagRepository(mockRepository.Object);
            dao.Update(new Tag { Id = 1, Name = "Tag 2" });

            Assert.AreEqual(1, mockObjectSet.Count());
            mockRepository.VerifyAll();
        }

        #endregion Udpate Tests

        #region Delete Tests

        /// <summary>
        /// Email template dao delete test with no matching record
        /// </summary>
        [TestMethod]
        public void TagDataManagerDeleteTagTestWithNoMatchingRecord()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            dao.Delete(new Tag { Id = 2 });

            Assert.AreEqual(1, mockObjectSet.Count());
        }

        /// <summary>
        /// Email template dao delete test with matching record
        /// </summary>
        [TestMethod]
        public void TagDataManagerDeleteTagTestWithMatchingRecord()
        {
            var mockObjectSet = new MockObjectSet<Tag>();
            mockObjectSet.AddObject(new Tag { Id = 1, Name = "Tag 1" });
            var mockRepository = new Mock<IDatabase>();
            mockRepository.SetupGet(m => m.Tags).Returns(mockObjectSet);
            var dao = new TagRepository(mockRepository.Object);
            dao.Delete(new Tag { Id = 1 });

            Assert.AreEqual(0, mockObjectSet.Count());
        }

        #endregion Delete Tests

        #endregion Tag Tests
    }
}